home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- From: thewalt@canuck.CE.Berkeley.EDU (Chris Thewalt)
- Subject: v25i056: input-edit - C input functions for line editing with history, Part01/01
- Message-ID: <1991Nov13.033151.17617@sparky.imd.sterling.com>
- X-Md4-Signature: 9dbf7f3e9d651adf33032942de7869c2
- Date: Wed, 13 Nov 1991 03:31:51 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: thewalt@canuck.CE.Berkeley.EDU (Chris Thewalt)
- Posting-number: Volume 25, Issue 56
- Archive-name: input-edit/part01
- Environment: UNIX, MS-DOS
-
- environment: ANSI C, UNIX (sysv or bsd) or MSDOS with MSC
- (Converting to K&R C should be fairly simple)
-
- tested on: DECstation 5000, Ultrix 4.2 with gcc
- Sun Sparc II, SunOS 4.1.1, gcc
- SGI Iris, IRIX System V.3, cc
- PC, DR DOS 5.0, MSC 6.0
-
- description: The input-edit package can be used in programs that
- want to provide an emacs style line editing cabability
- with history. The function getline allows the user to
- edit the current line and move through the history list
- of lines previously typed and returns the buffer to the
- caller when RETURN is entered. Long lines are handled
- by horizontal scrolling. Does NOT use termcap, uses
- only \b to move around.
-
- The actual editing capabilites are a very small subset
- of emacs commands, but then the package is very small
- and quite portable. Get GNU readline if you need more
- powerful editing.
-
- Chris (thewalt@ce.berkeley.edu)
- ---------------------------------------------------------------------
- #!/bin/sh
- # This is a shell archive (produced by shar 3.49)
- # To extract the files from this archive, save it to a file, remove
- # everything above the "!/bin/sh" line above, and type "sh file_name".
- #
- # made 11/09/1991 20:30 UTC by thewalt@canuck.CE.Berkeley.EDU
- # Source directory /usr/users/thewalt/et/gl
- #
- # existing files will NOT be overwritten unless -c is specified
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 1276 -rw-r--r-- README
- # 98 -rw-r--r-- Makefile
- # 17056 -rw-r--r-- getline.c
- # 293 -rw-r--r-- testgl.c
- #
- # ============= README ==============
- if test -f 'README' -a X"$1" != X"-c"; then
- echo 'x - skipping README (File already exists)'
- else
- echo 'x - extracting README (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'README' &&
- Send bug reports, fixes and enhancements to:
- Chris Thewalt (thewalt@ce.berkeley.edu)
- 11/9/91
- X
- A simple driver called testgl.c has been included, all it does is echo each
- line of input that is read. The user can perform editing and history
- manipulation before hitting RET.
- X
- The details of getline are all included as comments within getline.c
- X
- environment: ANSI C, UNIX (sysv or bsd) or MSDOS with MSC
- X (Converting to K&R C should be fairly simple)
- X
- tested on: DECstation 5000, Ultrix 4.2 with gcc
- X Sun Sparc II, SunOS 4.1.1, gcc
- X SGI Iris, IRIX System V.3, cc
- X PC, DR DOS 5.0, MSC 6.0
- X
- description: Getline can be used in programs that want to provide
- X an emacs style line editing cabability with history.
- X Getline allows the user to edit the current line
- X and move through the history list of lines previously
- X typed and returns the buffer to the caller when RETURN
- X is entered. Long lines are handled by scrolling.
- X Does NOT use termcap, uses only \b to move around.
- X
- X The actual editing capabilites are a very small subset
- X of emacs commands, but then the package is very small
- X and quite portable. Get GNU readline if you need more
- X powerful editing.
- SHAR_EOF
- chmod 0644 README ||
- echo 'restore of README failed'
- Wc_c="`wc -c < 'README'`"
- test 1276 -eq "$Wc_c" ||
- echo 'README: original size 1276, current size' "$Wc_c"
- fi
- # ============= Makefile ==============
- if test -f 'Makefile' -a X"$1" != X"-c"; then
- echo 'x - skipping Makefile (File already exists)'
- else
- echo 'x - extracting Makefile (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
- OBJS = testgl.o getline.o
- X
- testgl: $(OBJS)
- X $(CC) -o testgl $(OBJS)
- X
- clean:
- X rm -f $(OBJS) testgl
- SHAR_EOF
- chmod 0644 Makefile ||
- echo 'restore of Makefile failed'
- Wc_c="`wc -c < 'Makefile'`"
- test 98 -eq "$Wc_c" ||
- echo 'Makefile: original size 98, current size' "$Wc_c"
- fi
- # ============= getline.c ==============
- if test -f 'getline.c' -a X"$1" != X"-c"; then
- echo 'x - skipping getline.c (File already exists)'
- else
- echo 'x - extracting getline.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'getline.c' &&
- #ifndef lint
- static char rcsid[] =
- "$Id: getline.c,v 1.8 1991/11/09 20:27:48 thewalt Exp thewalt $";
- #endif
- X
- /*
- X * Fairly portable (ANSI C), emacs style line editing input package.
- X * This package uses \b to move, and \007 to ring the bell.
- X * It uses a fixed screen width, as initialized in the gl_init() call,
- X * and does not draw in the last location to avoid line wraps.
- X * The only non-portable part is how to turn off character echoing.
- X * This code works for *NIX of BSD or SYSV flavor, as well as MSDOS (MSC6.0).
- X * No TERMCAP features are used, so long lines are scrolled on one line
- X * rather than extending over several lines. The function getline
- X * returns a pointer to a static buffer area which holds the input string,
- X * including the newline. On EOF the first character is set equal to '\0'.
- X * The caller supplies a desired prompt, as shown in the prototype:
- X *
- X * char *getline(char *prompt)
- X *
- X * Getline is different from GNU readline in that:
- X * - getline has much more limited editing capabilities, but it
- X * is also much smaller and doesn't need termcap.
- X * - you don't free the buffer when done, since it is static
- X * (make a copy yourself if you want one)
- X * - the newline is appended to the buffer
- X * - you don't add lines to history, it is done automatically.
- X *
- X * The function gl_init(int screen_width) should be called before
- X * calling getline(char *prompt), and gl_cleanup(void) should be
- X * called before before exiting. The function gl_redraw(void) may also
- X * be called to redraw the screen (as is done when ^L or ^R are read).
- X *
- X * The editing keys are:
- X * ^A, ^E - move to beginnning or end of line, respectively.
- X * ^F, ^B - nondestructive move forward or back one location, respectively.
- X * ^D - delete the character currently under the cursor, or
- X * send EOF if no characters in the buffer.
- X * ^H, DEL - delete character left of the cursor.
- X * ^K - delete from cursor to end of line.
- X * ^P, ^N - move through history, previous and next, respectively.
- X * ^L, ^R - redraw the current line.
- X * TAB - call user defined function if bound, or insert spaces
- X * to get to next TAB stop (just past every 8th column).
- X * NL, CR - places line on history list if nonblank, calls output
- X * cleanup function if bound, appends newline and returns
- X * to the caller.
- X *
- X * In addition, the caller can modify the buffer in certain ways, which
- X * may be useful for things like auto-indent modes. There are three
- X * function pointers which can be bound to user functions.
- X * Each of these functions must return the index of the first location
- X * at which the buffer was modified, or -1 if the buffer wasn't modified.
- X * Each of the functions receive the current input buffer as the first
- X * argument. The screen is automatically cleaned up if the buffer is changed.
- X * The user is responsible for not writing beyond the end of the static
- X * buffer. The function pointer prototypes are:
- X *
- X * int (*gl_in_hook)(char *buf)
- X * - called on entry to getline, and each time a new history
- X * string is loaded, from a ^P or ^N. Initally NULL.
- X * int (*gl_out_hook)(char *buf)
- X * - called when a \n or \r is read, before appending \n and
- X * returning to caller. Initally NULL.
- X * int (*gl_tab_hook)(char *buf, int offset, int *loc)
- X * - called whenever a TAB is read. The second argument is
- X * the current line offset due to the width of the prompt.
- X * The third argument is a pointer to the variable holding the
- X * current location in the buffer. The location may be reset
- X * by the user to move the cursor when the call returns.
- X * Initially a built in tabbing function is bound.
- X *
- X * Please send bug reports, fixes and enhancements to Chris Thewalt,
- X * thewalt@ce.berkeley.edu
- X */
- X
- static char *copyright = "Copyright (C) 1991, Chris Thewalt";
- /*
- X * Copyright (C) 1991 by Chris Thewalt
- X *
- X * Permission to use, copy, modify, and distribute this software
- X * for any purpose and without fee is hereby granted, provided
- X * that the above copyright notices appear in all copies and that both the
- X * copyright notice and this permission notice appear in supporting
- X * documentation. This software is provided "as is" without express or
- X * implied warranty.
- X */
- X
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- X
- extern int isatty();
- X
- #define BUF_SIZE 1024
- #define SCROLL 30
- X
- static int gl_init_done = 0; /* -1 is terminal, 1 is batch */
- static int gl_screen = 80; /* screen width */
- static int gl_width = 0; /* net size available for input */
- static int gl_pos, gl_cnt = 0; /* position and size of input */
- static char gl_buf[BUF_SIZE]; /* input buffer */
- static char *gl_prompt; /* to save the prompt string */
- X
- void gl_init(int);
- void gl_cleanup(void); /* to undo gl_init */
- void gl_redraw(void); /* issue \n and redraw all */
- static void gl_char_init(void); /* get ready for no echo input */
- static void gl_char_cleanup(void); /* undo gl_char_init */
- static int gl_getchar(void); /* read one char from stdin */
- static void gl_addchar(int); /* install specified char */
- static void gl_newline(void); /* handle \n or \r */
- static void gl_fixup(int, int); /* fixup state variables and screen */
- static void gl_del(int); /* del, either left (-1) or cur (0) */
- static void gl_kill(void); /* delete to EOL */
- static int gl_tab(char *, int, int *); /* default TAB handler */
- X
- static void hist_add(void); /* adds nonblank entries to hist */
- static void hist_init(void); /* initializes hist pointers */
- static void hist_next(void); /* copies next entry to input buf */
- static void hist_prev(void); /* copies prev entry to input buf */
- static char *hist_save(char *); /* makes copy of a string */
- X
- int (*gl_in_hook)(char *) = 0;
- int (*gl_out_hook)(char *) = 0;
- int (*gl_tab_hook)(char *, int, int *) = gl_tab;
- X
- /************************ nonportable part *********************************/
- #ifdef MSDOS
- #include <bios.h>
- #endif
- X
- #ifdef unix
- #include <sys/ioctl.h>
- #ifndef TIOCGETP
- #include <termio.h>
- struct termio tty, old_tty;
- #else
- #include <sgtty.h>
- struct sgttyb tty, old_tty;
- #endif /* TIOCGETP */
- extern int ioctl();
- #endif /* unix */
- X
- static void
- gl_char_init()
- /* turn off input echo */
- {
- #ifdef unix
- #ifdef TIOCGETP
- X ioctl(0, TIOCGETP, &old_tty);
- X tty = old_tty;
- X tty.sg_flags |= CBREAK;
- X tty.sg_flags &= ~ECHO;
- X ioctl(0, TIOCSETP, &tty);
- #else
- X ioctl(0, TCGETA, &old_tty);
- X tty = old_tty;
- X tty.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
- X tty.c_cc[VMIN] = 1;
- X ioctl(0, TCSETA, &tty);
- #endif
- #endif /* unix */
- }
- X
- static void
- gl_char_cleanup()
- /* undo effects of gl_char_init, as necessary */
- {
- #ifdef unix
- #ifdef TIOCSETP
- X ioctl(0, TIOCSETP, &old_tty);
- #else
- X ioctl(0, TCSETA, &old_tty);
- #endif
- #endif /* unix */
- }
- X
- static int
- gl_getchar()
- /* get a character without echoing it to screen */
- {
- X int c;
- X
- #ifdef unix
- X c = fgetc(stdin);
- #endif
- #ifdef MSDOS
- X c = _bios_keybrd(_NKEYBRD_READ) & 0177; /* only using 7 bit ASCII */
- #endif
- X return c;
- }
- /******************** fairly portable part *********************************/
- void
- gl_init(int scrn_wdth)
- /* set up variables and terminal */
- {
- X gl_screen = scrn_wdth;
- X if (gl_init_done == 0) {
- X hist_init();
- X if (isatty(0) && isatty(1)) {
- X setvbuf(stdin, (char *)0, _IONBF, 0);
- X setvbuf(stdout, (char *)0, _IONBF, 0);
- X gl_char_init();
- X gl_init_done = -1; /* -1 means terminal */
- X } else {
- X gl_init_done = 1; /* 1 means batch */
- X }
- X }
- X gl_pos = gl_cnt = 0;
- }
- X
- void
- gl_cleanup()
- /* undo effects of gl_init, as necessary */
- {
- X if (gl_init_done == -1)
- X gl_char_cleanup();
- X gl_init_done = 0;
- }
- X
- char *
- getline(char *prompt)
- {
- X int c, loc, tmp;
- X
- X if (!gl_init_done)
- X gl_init(80);
- X gl_buf[0] = 0; /* used as end of input indicator */
- X if (gl_init_done == 1) { /* no input editing, and no prompt output */
- X fgets(gl_buf, BUF_SIZE, stdin);
- X return gl_buf;
- X }
- X gl_fixup(-1, 0); /* this resets gl_fixup */
- X gl_width = gl_screen - strlen(prompt);
- X if (prompt == NULL)
- X prompt = "";
- X gl_prompt = prompt;
- X gl_pos = gl_cnt = 0;
- X fputs(prompt, stdout);
- X if (gl_in_hook) {
- X loc = gl_in_hook(gl_buf);
- X if (loc >= 0)
- X gl_fixup(0, BUF_SIZE);
- X }
- X while ((c = gl_getchar()) != EOF) {
- X if (isprint(c)) {
- X gl_addchar(c);
- X } else {
- X switch (c) {
- X case '\n': case '\r': /* newline */
- X gl_newline();
- X return gl_buf;
- X break;
- X case '\001': gl_fixup(-1, 0); /* ^A */
- X break;
- X case '\002': gl_fixup(-1, gl_pos-1); /* ^B */
- X break;
- X case '\004': /* ^D */
- X if (gl_cnt == 0) {
- X gl_buf[0] = 0;
- X gl_cleanup();
- X fputc('\n', stdout);
- X return gl_buf;
- X } else {
- X gl_del(0);
- X }
- X break;
- X case '\005': gl_fixup(-1, gl_cnt); /* ^E */
- X break;
- X case '\006': gl_fixup(-1, gl_pos+1); /* ^F */
- X break;
- X case '\010': case '\177': gl_del(-1); /* ^H and DEL */
- X break;
- X case '\t': /* TAB */
- X if (gl_tab_hook) {
- X tmp = gl_pos;
- X loc = gl_tab_hook(gl_buf, strlen(gl_prompt), &tmp);
- X if (loc >= 0 || tmp != gl_pos)
- X gl_fixup(loc, tmp);
- X }
- X break;
- X case '\013': gl_kill(); /* ^K */
- X break;
- X case '\014': case '\022': gl_redraw(); /* ^L and ^R */
- X break;
- X case '\016': hist_next(); /* ^N */
- X break;
- X case '\020': hist_prev(); /* ^P */
- X break;
- X default:
- X fputc('\007', stdout);
- X break;
- X }
- X }
- X }
- X gl_cleanup();
- X return gl_buf;
- }
- X
- static void
- gl_addchar(int c)
- /* adds the character c to the input buffer at current location */
- {
- X int i;
- X
- X if (gl_cnt >= BUF_SIZE - 1) {
- X fprintf(stderr, "getline: input buffer overflow\n");
- X exit(1);
- X }
- X for (i=gl_cnt; i >= gl_pos; i--)
- X gl_buf[i+1] = gl_buf[i];
- X gl_buf[gl_pos] = c;
- X gl_fixup(gl_pos, gl_pos+1);
- }
- X
- static void
- gl_newline()
- /*
- X * Cleans up entire line before returning to caller. A \n is appended.
- X * If line longer than screen, we redraw starting at beginning
- X */
- {
- X int change = gl_cnt;
- X int len = gl_cnt;
- X int loc = gl_width - 5; /* shifts line back to start position */
- X
- X if (gl_cnt >= BUF_SIZE - 1) {
- X fprintf(stderr, "getline: input buffer overflow\n");
- X exit(1);
- X }
- X hist_add(); /* only adds if nonblank */
- X if (gl_out_hook) {
- X change = gl_out_hook(gl_buf);
- X len = strlen(gl_buf);
- X }
- X if (loc > len)
- X loc = len;
- X gl_fixup(change, loc); /* must do this before appending \n */
- X gl_buf[len] = '\n';
- X gl_buf[len+1] = '\0';
- X fputc('\n', stdout);
- }
- X
- static void
- gl_del(int loc)
- /*
- X * Delete a character. The loc variable can be:
- X * -1 : delete character to left of cursor
- X * 0 : delete character under cursor
- X */
- {
- X int i;
- X
- X if (loc == -1 && gl_pos > 0 || loc == 0 && gl_pos < gl_cnt) {
- X for (i=gl_pos+loc; i < gl_cnt; i++)
- X gl_buf[i] = gl_buf[i+1];
- X gl_fixup(gl_pos+loc, gl_pos+loc);
- X } else
- X fputc('\007', stdout);
- }
- X
- static void
- gl_kill()
- /* delete from current position to the end of line */
- {
- X if (gl_pos < gl_cnt) {
- X gl_buf[gl_pos] = '\0';
- X gl_fixup(gl_pos, gl_pos);
- X } else
- X fputc('\007', stdout);
- }
- X
- void
- gl_redraw()
- /* emit a newline, reset and redraw prompt and current input line */
- {
- X if (gl_init_done == -1) {
- X fputc('\n', stdout);
- X fputs(gl_prompt, stdout);
- X gl_pos = 0;
- X gl_fixup(0, BUF_SIZE);
- X }
- }
- X
- static void
- gl_fixup(int change, int cursor)
- /*
- X * This function is used both for redrawing when input changes or for
- X * moving within the input line. The parameters are:
- X * change : the index of the start of changes in the input buffer,
- X * with -1 indicating no changes.
- X * cursor : the desired location of the cursor after the call.
- X * A value of BUF_SIZE can be used to indicate the cursor should
- X * move just past the end of the input line.
- X */
- {
- X static int gl_shift; /* index of first on screen character */
- X static int off_right; /* true if more text right of screen */
- X static int off_left; /* true if more text left of screen */
- X int left = 0, right = -1; /* bounds for redraw */
- X int pad; /* how much to erase at end of line */
- X int backup; /* how far to backup before fixing */
- X int new_shift; /* value of shift based on cursor */
- X int extra; /* adjusts when shift (scroll) happens */
- X int i;
- X
- X if (change == -1 && cursor == 0 && gl_buf[0] == 0) { /* reset */
- X gl_shift = off_right = off_left = 0;
- X return;
- X }
- X pad = (off_right)? gl_width - 1 : gl_cnt - gl_shift; /* old length */
- X backup = gl_pos - gl_shift;
- X if (change >= 0) {
- X gl_cnt = strlen(gl_buf);
- X if (change > gl_cnt)
- X change = gl_cnt;
- X }
- X if (cursor > gl_cnt) {
- X if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */
- X fputc('\007', stdout);
- X cursor = gl_cnt;
- X }
- X if (cursor < 0) {
- X fputc('\007', stdout);
- X cursor = 0;
- X }
- X if (off_right || off_left && cursor < gl_shift + gl_width - SCROLL / 2)
- X extra = 2; /* shift the scrolling boundary */
- X else
- X extra = 0;
- X new_shift = cursor + extra + SCROLL - gl_width;
- X if (new_shift > 0) {
- X new_shift /= SCROLL;
- X new_shift *= SCROLL;
- X } else
- X new_shift = 0;
- X if (new_shift != gl_shift) { /* scroll occurs */
- X gl_shift = new_shift;
- X off_left = (gl_shift)? 1 : 0;
- X off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
- X left = gl_shift;
- X right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
- X } else if (change >= 0) { /* no scroll, but text changed */
- X if (change < gl_shift + off_left) {
- X left = gl_shift;
- X } else {
- X left = change;
- X backup = gl_pos - change;
- X }
- X off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
- X right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
- X }
- X pad -= (off_right)? gl_width - 1 : gl_cnt - gl_shift;
- X pad = (pad < 0)? 0 : pad;
- X if (left <= right) { /* clean up screen */
- X for (i=0; i < backup; i++)
- X fputc('\b', stdout);
- X if (left == gl_shift && off_left) {
- X fputc('$', stdout);
- X left++;
- X }
- X for (i=left; i < right; i++)
- X fputc(gl_buf[i], stdout);
- X if (off_right) {
- X fputc('$', stdout);
- X gl_pos = right + 1;
- X } else {
- X for (i=0; i < pad; i++) /* erase remains of prev line */
- X fputc(' ', stdout);
- X gl_pos = right + pad;
- X }
- X }
- X i = gl_pos - cursor; /* move to final cursor location */
- X if (i > 0) {
- X while (i--)
- X fputc('\b', stdout);
- X } else {
- X for (i=gl_pos; i < cursor; i++)
- X fputc(gl_buf[i], stdout);
- X }
- X gl_pos = cursor;
- }
- X
- static int
- gl_tab(char *buf, int offset, int *loc)
- /* default tab handler, acts like tabstops every 8 cols */
- {
- X int i, count, len;
- X
- X len = strlen(buf);
- X count = 8 - (offset + *loc) % 8;
- X for (i=len; i >= *loc; i--)
- X buf[i+count] = buf[i];
- X for (i=0; i < count; i++)
- X buf[*loc+i] = ' ';
- X i = *loc;
- X *loc = i + count;
- X return i;
- }
- X
- /******************* History stuff **************************************/
- X
- #ifndef HIST_SIZE
- #define HIST_SIZE 100
- #endif
- X
- int hist_pos, hist_last;
- char *hist_buf[HIST_SIZE];
- X
- static void
- hist_init()
- {
- X int i;
- X
- X for (i=0; i < HIST_SIZE; i++)
- X hist_buf[i] = (char *)NULL;
- }
- X
- static void
- hist_add()
- {
- X char *p = gl_buf;
- X
- X while (*p == ' ' || *p == '\t') /* only save nonblank line */
- X p++;
- X if (*p) {
- X hist_buf[hist_last] = hist_save(gl_buf);
- X hist_last = (hist_last + 1) % HIST_SIZE;
- X if (hist_buf[hist_last]) { /* erase next location */
- X free(hist_buf[hist_last]);
- X hist_buf[hist_last] = NULL;
- X }
- X }
- X hist_pos = hist_last;
- }
- X
- static void
- hist_prev()
- /* loads previous hist entry into input buffer, sticks on first */
- {
- X int next;
- X
- X next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
- X if (next != hist_last) {
- X if (hist_buf[next]) {
- X hist_pos = next;
- X strcpy(gl_buf, hist_buf[hist_pos]);
- X } else
- X fputc('\007', stdout);
- X } else
- X fputc('\007', stdout);
- X if (gl_in_hook)
- X gl_in_hook(gl_buf);
- X gl_fixup(0, BUF_SIZE);
- }
- X
- static void
- hist_next()
- /* loads next hist entry into input buffer, clears on last */
- {
- X if (hist_pos != hist_last) {
- X hist_pos = (hist_pos + 1) % HIST_SIZE;
- X if (hist_buf[hist_pos]) {
- X strcpy(gl_buf, hist_buf[hist_pos]);
- X } else {
- X gl_buf[0] = 0;
- X }
- X } else
- X fputc('\007', stdout);
- X if (gl_in_hook)
- X gl_in_hook(gl_buf);
- X gl_fixup(0, BUF_SIZE);
- }
- X
- static char *
- hist_save(char *p)
- /* makes a copy of the string */
- {
- X char *s = NULL;
- X
- X if (p && ((s = malloc(strlen(p)+1)) != NULL)) {
- X strcpy(s, p);
- X }
- X return s;
- }
- SHAR_EOF
- chmod 0644 getline.c ||
- echo 'restore of getline.c failed'
- Wc_c="`wc -c < 'getline.c'`"
- test 17056 -eq "$Wc_c" ||
- echo 'getline.c: original size 17056, current size' "$Wc_c"
- fi
- # ============= testgl.c ==============
- if test -f 'testgl.c' -a X"$1" != X"-c"; then
- echo 'x - skipping testgl.c (File already exists)'
- else
- echo 'x - extracting testgl.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'testgl.c' &&
- #include <stdio.h>
- X
- char *getline(char *);
- void gl_init(int), gl_cleanup(void);
- X
- main()
- /*
- X * just echo user input lines, letting user edit them and move through
- X * history list
- X */
- {
- X char *p;
- X
- X gl_init(80);
- X while ((p = getline("> ")) && *p)
- X fputs(p, stdout);
- X gl_cleanup();
- }
- SHAR_EOF
- chmod 0644 testgl.c ||
- echo 'restore of testgl.c failed'
- Wc_c="`wc -c < 'testgl.c'`"
- test 293 -eq "$Wc_c" ||
- echo 'testgl.c: original size 293, current size' "$Wc_c"
- fi
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-